Trò chơi Angry Birds trong UNITY Engine
31.714 lượt xem;
1 using UnityEngine;
2 using System;
3 using System.Collections;
4 using System.Collections.Generic;
5
6
7 public class GoTween : AbstractGoTween
8 {
9 // Tween specific properties
10 public object target { get; private set; } // the target of the tweens
11 public float delay { get; private set; } // delay before starting the actual animations
12 private float _elapsedDelay; // total time delayed
13 private bool _delayComplete; // once we complete the delay this gets set so we can reverse and play properly for the future
14 public bool isFrom { get; private set; } // a value of true will make this a "from" tween
15
16 private List<AbstractTweenProperty> _tweenPropertyList = new List<AbstractTweenProperty>();
17 private string targetTypeString;
18
19 /// <summary>
20 /// sets the ease type for all Tweens. this will overwrite the ease types for each Tween!
21 /// </summary>
22 private GoEaseType _easeType;
23 public GoEaseType easeType
24 {
25 get
26 {
27 return _easeType;
28 }
29 set
30 {
31 _easeType = value;
32
33 // change ease type of all existing tweens.
34 foreach( var tween in _tweenPropertyList )
35 tween.setEaseType( value );
36 }
37 }
38
39
40 /// <summary>
41 /// initializes a new instance and sets up the details according to the config parameter
42 /// </summary>
43 public GoTween( object target, float duration, GoTweenConfig config, Action<AbstractGoTween> onComplete = null )
44 {
45 // default to removing on complete
46 autoRemoveOnComplete = true;
47
48 // allow events by default
49 allowEvents = true;
50
51 // setup callback bools
52 _didInit = false;
53 _didBegin = false;
54
55 // flag the onIterationStart event to fire.
56 // as long as goTo is not called on this tween, the onIterationStart event will fire
57 // as soon as the delay, if any, is completed.
58 _fireIterationStart = true;
59
60 this.target = target;
61 this.targetTypeString = target.GetType().ToString();
62 this.duration = duration;
63
64 // copy the TweenConfig info over
65 id = config.id;
66 delay = config.delay;
67 loopType = config.loopType;
68 iterations = config.iterations;
69 _easeType = config.easeType;
70 updateType = config.propertyUpdateType;
71 isFrom = config.isFrom;
72 timeScale = config.timeScale;
73
74 _onInit = config.onInitHandler;
75 _onBegin = config.onBeginHandler;
76 _onIterationStart = config.onIterationStartHandler;
77 _onUpdate = config.onUpdateHandler;
78 _onIterationEnd = config.onIterationEndHandler;
79 _onComplete = config.onCompleteHandler;
80
81 if( config.isPaused )
82 state = GoTweenState.Paused;
83
84 // if onComplete is passed to the constructor it wins. it is left as the final param to allow an inline Action to be
85 // set and maintain clean code (Actions always try to be the last param of a method)
86 if( onComplete != null )
87 _onComplete = onComplete;
88
89 // add all our properties
90 for( var i = 0; i < config.tweenProperties.Count; ++i )
91 {
92 var tweenProp = config.tweenProperties[i];
93
94 // if the tween property is initialized already it means it is being reused so we need to clone it
95 if( tweenProp.isInitialized )
96 tweenProp = tweenProp.clone();
97
98 addTweenProperty( tweenProp );
99 }
100
101 // calculate total duration
102 if( iterations < 0 )
103 totalDuration = float.PositiveInfinity;
104 else
105 totalDuration = iterations * duration;
106 }
107
108 /// <summary>
109 /// tick method. if it returns true it indicates the tween is complete
110 /// </summary>
111 public override bool update( float deltaTime )
112 {
113 // properties are prepared only once on the first update of the tween.
114 if ( !_didInit )
115 onInit();
116
117 // should we validate the target?
118 if( Go.validateTargetObjectsEachTick )
119 {
120 // This might seem to be overkill, but on the case of Transforms that
121 // have been destroyed, target == null will return false, whereas
122 // target.Equals(null) will return true. Otherwise we don't really
123 // get the benefits of the nanny.
124 if( target == null || target.Equals(null) )
125 {
126 // if the target doesn't pass validation
127 Debug.LogWarning( "target validation failed. destroying the tween to avoid errors. Target type: " + this.targetTypeString );
128 autoRemoveOnComplete = true;
129 return true;
130 }
131 }
132
133 // we only fire the begin callback once per run.
134 if ( !_didBegin )
135 onBegin();
136
137 // handle delay and return if we are still delaying
138 if( !_delayComplete && _elapsedDelay < delay )
139 {
140 // if we have a timeScale set we need to remove its influence so that delays are always in seconds
141 if( timeScale != 0 )
142 _elapsedDelay += deltaTime / timeScale;
143
144 // are we done delaying?
145 if( _elapsedDelay >= delay )
146 _delayComplete = true;
147
148 return false;
149 }
150
151 // loops only start once the delay has completed.
152 if ( _fireIterationStart )
153 onIterationStart();
154
155 // base will calculate the proper elapsedTime, iterations, etc.
156 base.update( deltaTime );
157
158 // if we are looping back on a PingPong loop
159 var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;
160 //Debug.Log(string.Format("{0} : {1} -- {2}", _elapsedTime, convertedElapsedTime, _isLoopingBackOnPingPong ? "Y" : "N"));
161
162 // update all properties
163 for( var i = 0; i < _tweenPropertyList.Count; ++i )
164 _tweenPropertyList[i].tick( convertedElapsedTime );
165
166 onUpdate();
167
168 if ( _fireIterationEnd )
169 onIterationEnd();
170
171 if( state == GoTweenState.Complete )
172 {
173 onComplete();
174
175 return true; // true if complete
176 }
177
178 return false; // false if not complete
179 }
180
181
182 /// <summary>
183 /// we are valid if we have a target and at least one TweenProperty
184 /// </summary>
185 public override bool isValid()
186 {
187 return target != null;
188 }
189
190
191 /// <summary>
192 /// adds the tween property if it passes validation and initializes the property
193 /// </summary>
194 public void addTweenProperty( AbstractTweenProperty tweenProp )
195 {
196 // make sure the target is valid for this tween before adding
197 if( tweenProp.validateTarget( target ) )
198 {
199 // ensure we dont add two tweens of the same property so they dont fight
200 if( _tweenPropertyList.Contains( tweenProp ) )
201 {
202 Debug.Log( "not adding tween property because one already exists: " + tweenProp );
203 return;
204 }
205
206 _tweenPropertyList.Add( tweenProp );
207 tweenProp.init( this );
208 }
209 else
210 {
211 Debug.Log( "tween failed to validate target: " + tweenProp );
212 }
213 }
214
215
216 public override bool removeTweenProperty( AbstractTweenProperty property )
217 {
218 if( _tweenPropertyList.Contains( property ) )
219 {
220 _tweenPropertyList.Remove( property );
221 return true;
222 }
223
224 return false;
225 }
226
227
228 public override bool containsTweenProperty( AbstractTweenProperty property )
229 {
230 return _tweenPropertyList.Contains( property );
231 }
232
233
234 public void clearTweenProperties()
235 {
236 _tweenPropertyList.Clear();
237 }
238
239
240 public override List<AbstractTweenProperty> allTweenProperties()
241 {
242 return _tweenPropertyList;
243 }
244
245
246 #region AbstractTween overrides
247
248 /// <summary>
249 /// called only once the first update of a tween.
250 /// </summary>
251 protected override void onInit()
252 {
253 base.onInit();
254
255 for ( var i = 0; i < _tweenPropertyList.Count; ++i )
256 _tweenPropertyList[i].prepareForUse();
257 }
258
259 /// <summary>
260 /// removes the tween and cleans up its state
261 /// </summary>
262 public override void destroy()
263 {
264 base.destroy();
265
266 _tweenPropertyList.Clear();
267 target = null;
268 }
269
270 /// <summary>
271 /// goes to the specified time clamping it from 0 to the total duration of the tween. if the tween is
272 /// not playing it will be force updated to the time specified.
273 /// </summary>
274 public override void goTo( float time , bool skipDelay = true )
275 {
276 // handle delay, which is specific to Tweens
277 if( skipDelay )
278 {
279 _elapsedDelay = delay;
280 }
281 else
282 {
283 _elapsedDelay = Mathf.Min( time, delay );
284 time -= _elapsedDelay;
285 }
286
287 _delayComplete = _elapsedDelay >= delay;
288
289 time = Mathf.Clamp( time, 0f, totalDuration );
290
291 // provide an early out for calling goto on the same time multiple times.
292 if ( time == _totalElapsedTime )
293 return;
294
295 // if we are doing a goTo at the "start" of the timeline, based on the isReversed variable,
296 // allow the onBegin and onIterationStart callback to fire again.
297 // we only allow the onIterationStart event callback to fire at the start of the timeline,
298 // as doing a goTo(x) where x % duration == 0 will trigger the onIterationEnd before we
299 // go to the start.
300 if ( ( isReversed && time == totalDuration ) || ( !isReversed && time == 0f ) )
301 {
302 _didBegin = false;
303 _fireIterationStart = true;
304 }
305 else
306 {
307 _didBegin = true;
308 _fireIterationStart = false;
309 }
310
311 // since we're doing a goTo, we want to stop this tween from remembering that it iterated.
312 // this could cause issues if you caused the tween to complete an iteration and then goTo somewhere
313 // else while still paused.
314 _didIterateThisFrame = false;
315
316 // force a time and completedIterations before we update
317 _totalElapsedTime = time;
318 _completedIterations = isReversed ? Mathf.CeilToInt( _totalElapsedTime / duration ) : Mathf.FloorToInt( _totalElapsedTime / duration );
319
320 update( 0 );
321 }
322
323
324 /// <summary>
325 /// completes the tween. sets the object to it's final position as if the tween completed normally.
326 /// takes into effect if the tween was playing forward or reversed.
327 /// </summary>
328 public override void complete()
329 {
330 if( iterations < 0 )
331 return;
332
333 // set delayComplete so we get one last update in before we die (base will set the elapsed time for us)
334 _delayComplete = true;
335
336 base.complete();
337 }
338
339 #endregion
340
341 }
2 using System;
3 using System.Collections;
4 using System.Collections.Generic;
5
6
7 public class GoTween : AbstractGoTween
8 {
9 // Tween specific properties
10 public object target { get; private set; } // the target of the tweens
11 public float delay { get; private set; } // delay before starting the actual animations
12 private float _elapsedDelay; // total time delayed
13 private bool _delayComplete; // once we complete the delay this gets set so we can reverse and play properly for the future
14 public bool isFrom { get; private set; } // a value of true will make this a "from" tween
15
16 private List<AbstractTweenProperty> _tweenPropertyList = new List<AbstractTweenProperty>();
17 private string targetTypeString;
18
19 /// <summary>
20 /// sets the ease type for all Tweens. this will overwrite the ease types for each Tween!
21 /// </summary>
22 private GoEaseType _easeType;
23 public GoEaseType easeType
24 {
25 get
26 {
27 return _easeType;
28 }
29 set
30 {
31 _easeType = value;
32
33 // change ease type of all existing tweens.
34 foreach( var tween in _tweenPropertyList )
35 tween.setEaseType( value );
36 }
37 }
38
39
40 /// <summary>
41 /// initializes a new instance and sets up the details according to the config parameter
42 /// </summary>
43 public GoTween( object target, float duration, GoTweenConfig config, Action<AbstractGoTween> onComplete = null )
44 {
45 // default to removing on complete
46 autoRemoveOnComplete = true;
47
48 // allow events by default
49 allowEvents = true;
50
51 // setup callback bools
52 _didInit = false;
53 _didBegin = false;
54
55 // flag the onIterationStart event to fire.
56 // as long as goTo is not called on this tween, the onIterationStart event will fire
57 // as soon as the delay, if any, is completed.
58 _fireIterationStart = true;
59
60 this.target = target;
61 this.targetTypeString = target.GetType().ToString();
62 this.duration = duration;
63
64 // copy the TweenConfig info over
65 id = config.id;
66 delay = config.delay;
67 loopType = config.loopType;
68 iterations = config.iterations;
69 _easeType = config.easeType;
70 updateType = config.propertyUpdateType;
71 isFrom = config.isFrom;
72 timeScale = config.timeScale;
73
74 _onInit = config.onInitHandler;
75 _onBegin = config.onBeginHandler;
76 _onIterationStart = config.onIterationStartHandler;
77 _onUpdate = config.onUpdateHandler;
78 _onIterationEnd = config.onIterationEndHandler;
79 _onComplete = config.onCompleteHandler;
80
81 if( config.isPaused )
82 state = GoTweenState.Paused;
83
84 // if onComplete is passed to the constructor it wins. it is left as the final param to allow an inline Action to be
85 // set and maintain clean code (Actions always try to be the last param of a method)
86 if( onComplete != null )
87 _onComplete = onComplete;
88
89 // add all our properties
90 for( var i = 0; i < config.tweenProperties.Count; ++i )
91 {
92 var tweenProp = config.tweenProperties[i];
93
94 // if the tween property is initialized already it means it is being reused so we need to clone it
95 if( tweenProp.isInitialized )
96 tweenProp = tweenProp.clone();
97
98 addTweenProperty( tweenProp );
99 }
100
101 // calculate total duration
102 if( iterations < 0 )
103 totalDuration = float.PositiveInfinity;
104 else
105 totalDuration = iterations * duration;
106 }
107
108 /// <summary>
109 /// tick method. if it returns true it indicates the tween is complete
110 /// </summary>
111 public override bool update( float deltaTime )
112 {
113 // properties are prepared only once on the first update of the tween.
114 if ( !_didInit )
115 onInit();
116
117 // should we validate the target?
118 if( Go.validateTargetObjectsEachTick )
119 {
120 // This might seem to be overkill, but on the case of Transforms that
121 // have been destroyed, target == null will return false, whereas
122 // target.Equals(null) will return true. Otherwise we don't really
123 // get the benefits of the nanny.
124 if( target == null || target.Equals(null) )
125 {
126 // if the target doesn't pass validation
127 Debug.LogWarning( "target validation failed. destroying the tween to avoid errors. Target type: " + this.targetTypeString );
128 autoRemoveOnComplete = true;
129 return true;
130 }
131 }
132
133 // we only fire the begin callback once per run.
134 if ( !_didBegin )
135 onBegin();
136
137 // handle delay and return if we are still delaying
138 if( !_delayComplete && _elapsedDelay < delay )
139 {
140 // if we have a timeScale set we need to remove its influence so that delays are always in seconds
141 if( timeScale != 0 )
142 _elapsedDelay += deltaTime / timeScale;
143
144 // are we done delaying?
145 if( _elapsedDelay >= delay )
146 _delayComplete = true;
147
148 return false;
149 }
150
151 // loops only start once the delay has completed.
152 if ( _fireIterationStart )
153 onIterationStart();
154
155 // base will calculate the proper elapsedTime, iterations, etc.
156 base.update( deltaTime );
157
158 // if we are looping back on a PingPong loop
159 var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;
160 //Debug.Log(string.Format("{0} : {1} -- {2}", _elapsedTime, convertedElapsedTime, _isLoopingBackOnPingPong ? "Y" : "N"));
161
162 // update all properties
163 for( var i = 0; i < _tweenPropertyList.Count; ++i )
164 _tweenPropertyList[i].tick( convertedElapsedTime );
165
166 onUpdate();
167
168 if ( _fireIterationEnd )
169 onIterationEnd();
170
171 if( state == GoTweenState.Complete )
172 {
173 onComplete();
174
175 return true; // true if complete
176 }
177
178 return false; // false if not complete
179 }
180
181
182 /// <summary>
183 /// we are valid if we have a target and at least one TweenProperty
184 /// </summary>
185 public override bool isValid()
186 {
187 return target != null;
188 }
189
190
191 /// <summary>
192 /// adds the tween property if it passes validation and initializes the property
193 /// </summary>
194 public void addTweenProperty( AbstractTweenProperty tweenProp )
195 {
196 // make sure the target is valid for this tween before adding
197 if( tweenProp.validateTarget( target ) )
198 {
199 // ensure we dont add two tweens of the same property so they dont fight
200 if( _tweenPropertyList.Contains( tweenProp ) )
201 {
202 Debug.Log( "not adding tween property because one already exists: " + tweenProp );
203 return;
204 }
205
206 _tweenPropertyList.Add( tweenProp );
207 tweenProp.init( this );
208 }
209 else
210 {
211 Debug.Log( "tween failed to validate target: " + tweenProp );
212 }
213 }
214
215
216 public override bool removeTweenProperty( AbstractTweenProperty property )
217 {
218 if( _tweenPropertyList.Contains( property ) )
219 {
220 _tweenPropertyList.Remove( property );
221 return true;
222 }
223
224 return false;
225 }
226
227
228 public override bool containsTweenProperty( AbstractTweenProperty property )
229 {
230 return _tweenPropertyList.Contains( property );
231 }
232
233
234 public void clearTweenProperties()
235 {
236 _tweenPropertyList.Clear();
237 }
238
239
240 public override List<AbstractTweenProperty> allTweenProperties()
241 {
242 return _tweenPropertyList;
243 }
244
245
246 #region AbstractTween overrides
247
248 /// <summary>
249 /// called only once the first update of a tween.
250 /// </summary>
251 protected override void onInit()
252 {
253 base.onInit();
254
255 for ( var i = 0; i < _tweenPropertyList.Count; ++i )
256 _tweenPropertyList[i].prepareForUse();
257 }
258
259 /// <summary>
260 /// removes the tween and cleans up its state
261 /// </summary>
262 public override void destroy()
263 {
264 base.destroy();
265
266 _tweenPropertyList.Clear();
267 target = null;
268 }
269
270 /// <summary>
271 /// goes to the specified time clamping it from 0 to the total duration of the tween. if the tween is
272 /// not playing it will be force updated to the time specified.
273 /// </summary>
274 public override void goTo( float time , bool skipDelay = true )
275 {
276 // handle delay, which is specific to Tweens
277 if( skipDelay )
278 {
279 _elapsedDelay = delay;
280 }
281 else
282 {
283 _elapsedDelay = Mathf.Min( time, delay );
284 time -= _elapsedDelay;
285 }
286
287 _delayComplete = _elapsedDelay >= delay;
288
289 time = Mathf.Clamp( time, 0f, totalDuration );
290
291 // provide an early out for calling goto on the same time multiple times.
292 if ( time == _totalElapsedTime )
293 return;
294
295 // if we are doing a goTo at the "start" of the timeline, based on the isReversed variable,
296 // allow the onBegin and onIterationStart callback to fire again.
297 // we only allow the onIterationStart event callback to fire at the start of the timeline,
298 // as doing a goTo(x) where x % duration == 0 will trigger the onIterationEnd before we
299 // go to the start.
300 if ( ( isReversed && time == totalDuration ) || ( !isReversed && time == 0f ) )
301 {
302 _didBegin = false;
303 _fireIterationStart = true;
304 }
305 else
306 {
307 _didBegin = true;
308 _fireIterationStart = false;
309 }
310
311 // since we're doing a goTo, we want to stop this tween from remembering that it iterated.
312 // this could cause issues if you caused the tween to complete an iteration and then goTo somewhere
313 // else while still paused.
314 _didIterateThisFrame = false;
315
316 // force a time and completedIterations before we update
317 _totalElapsedTime = time;
318 _completedIterations = isReversed ? Mathf.CeilToInt( _totalElapsedTime / duration ) : Mathf.FloorToInt( _totalElapsedTime / duration );
319
320 update( 0 );
321 }
322
323
324 /// <summary>
325 /// completes the tween. sets the object to it's final position as if the tween completed normally.
326 /// takes into effect if the tween was playing forward or reversed.
327 /// </summary>
328 public override void complete()
329 {
330 if( iterations < 0 )
331 return;
332
333 // set delayComplete so we get one last update in before we die (base will set the elapsed time for us)
334 _delayComplete = true;
335
336 base.complete();
337 }
338
339 #endregion
340
341 }